﻿using System;
using System.Collections.Generic;
using System.Xml;
using biz.ritter.javapi.xml;
using biz.ritter.javapi.lang;
using Nofs.Net.Common.Interfaces.Cache;

namespace Nofs.Net.Cache.Impl
{

    public sealed class DocumentHelper
    {
        public static Document createDocument()
        {
            return new Document();
        }

        public static Document parseText(String data)
        {
            Document xmlDoc = new Document();
            xmlDoc.LoadXml(data);
            return xmlDoc;

        }
    }


    public class XmlRepresentationBuilder : IRepresentationBuilder
    {
        private Document _document;

        public XmlRepresentationBuilder()
        {
            _document = DocumentHelper.createDocument();
        }

        public void PopulateWith(String data) //throws NoFSSerializationException 
        {
            try
            {
                _document = DocumentHelper.parseText(data.trim());
            }
            catch (System.Xml.XmlException de)
            {
                throw new NoFSSerializationException(de);
            }
        }

        private class XmlFolderReference : IFolderReference
        {
            public Branch branch;

            public XmlFolderReference(Branch branch)
            {
                this.branch = branch;
            }

            //@Override
            public String getName()
            {
                return branch.LocalName;
            }
        }

        public String TranslateToString() // throws Exception 
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();

            using (System.IO.StringWriter sw = new System.IO.StringWriter(sb))
            using (XmlTextWriter writer = new XmlTextWriter(sw))
            {
                writer.Formatting = Formatting.Indented;
                _document.Save(writer);
                writer.Flush();
            }

            return sb.toString();

        }

        //@Override
        public IFolderReference GetRoot()
        {
            return new XmlFolderReference(_document);
        }

        //@Override
        public IFolderReference AddFolder(IFolderReference folder, String name)
        {
            XmlNode newNode = ((XmlFolderReference)folder).branch.OwnerDocument.CreateElement(name);
            return new XmlFolderReference(((XmlFolderReference)folder).branch.AppendChild(newNode));
        }

        //@Override
        //@SuppressWarnings("unchecked")
        public IFolderReference FindChildByName(IFolderReference parent, String name)// throws Exception 
        {
            for (XmlNode iter = ((XmlFolderReference)parent).branch; iter.HasChildNodes; )
            {
                Object obj = iter.NextSibling;
                if (obj is XmlNode)
                {
                    XmlNode child = (XmlNode)obj;
                    if (child.LocalName.compareTo(name) == 0)
                    {
                        return new XmlFolderReference(child);
                    }
                }
            }
            throw new System.Exception("could not find xml node: '" + name + "' as child of '" + parent.getName() + "'");
        }

        //@Override
        //@SuppressWarnings("unchecked")
        public List<IFolderReference> GetChildren(IFolderReference folder)
        {
            List<IFolderReference> children = new List<IFolderReference>();
            for (XmlNode iter = ((XmlFolderReference)folder).branch; iter.HasChildNodes; )
            {
                Object obj = iter.NextSibling;
                if (obj is XmlNode)
                {
                    children.Add(new XmlFolderReference((XmlNode)obj));
                }
            }
            return children;
        }

        //@Override
        public String GetFolderValue(IFolderReference folder)
        {
            return ((XmlFolderReference)folder).branch.InnerText;
        }

        //@Override
        public void SetFolderValue(IFolderReference folder, Object value)
        {
            ((XmlFolderReference)folder).branch.InnerText = value.toString();
        }

    }

}
